<template>
    <div></div>
    <div ref="terminalRef">
    </div>
</template>
<script setup lang="ts">
import {Terminal} from 'xterm'
import {FitAddon} from 'xterm-addon-fit';
import {SearchAddon} from 'xterm-addon-search';
import {WebLinksAddon} from 'xterm-addon-web-links';
import { AttachAddon } from "xterm-addon-attach";
import {onBeforeUnmount, onMounted, ref} from "vue";

import axios from "axios";

const terminalRef = ref<HTMLElement|null>(null);
const socketURL = "ws://127.0.0.1:4000/socket/";
let terminal,ws;
onMounted(()=>{
    initTerminal()
    initWs()
})


onBeforeUnmount(()=>{
    terminal?.dispose?.();
})

const fitAddon = new FitAddon();
function initTerminal(){
    if(!terminalRef.value) return;
    terminal = new Terminal({
        cols:160,
        cursorBlink: true, // 光标闪烁
        cursorStyle: "block", // 光标样式  null | 'block' | 'underline' | 'bar'
        tabStopWidth: 8, //制表宽度
        screenKeys: true,
        fontFamily: 'Menlo, Monaco, "Courier New", monospace',
        fontWeight: 400,
        fontSize: 14,
        rows: 200,
    });

    terminal.loadAddon(fitAddon);
    fitAddon.fit();
    const searchAddon = new SearchAddon();
    terminal.loadAddon(searchAddon);

    const linksAddon = new WebLinksAddon();
    terminal.loadAddon(linksAddon);
    terminal.open(terminalRef.value);
    terminal.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ')
    // 监听数据
    terminal.onData((data) => {
        terminal.write(data)
    })

    terminal.onRender((data:{ start: number, end: number })=>{
        console.log('onRender',data);
    })
}
//初始化当前系统环境，返回终端的 pid，标识当前终端的唯一性
const initSysEnv = async () =>{
    try {
        const {data} =  await axios.post("http://127.0.0.1:4000/terminal")
        return data
    }catch (err) {
        throw new Error(err);
    }
}


async function initWs(){
    const pid = await initSysEnv(terminal)
     ws = new WebSocket(socketURL + pid);
    terminal.onResize(({cols, rows}) => {
        if (ws.readyState === 1) {
            ws.send(JSON.stringify({resize: [cols, rows]}))
        }
    });
     const attachAddon = new AttachAddon(ws);
     terminal.loadAddon(attachAddon);
    window.addEventListener('resize', fitTerminal)
}

function fitTerminal() {
    const dims = fitAddon.proposeDimensions();
    if (!dims || !terminal || !dims.cols || !dims.rows) return;
    if (terminal.rows !== dims.rows || terminal.cols !== dims.cols) {
        terminal._core._renderService.clear();
        terminal.resize(dims.cols, dims.rows);
    }
}

onBeforeUnmount(()=>{
    window.removeEventListener("resize", fitTerminal)
})
</script>
